{INCLUDE FILE UABC4 -- IMPLEMENTATION OF UABC}
{Copyright 1983, 1984, Apple Computer, Inc.}

                                {TWindow-TDialogBox-TMenuBar-TFont}


{changed 05/07/84 17:45 Fixed (hopefully) a bug in binary search of InAllMenusDo.}

METHODS OF TWindow;


    {$S SgABCini}
    FUNCTION  {TWindow.}CREATE{(object: TObject; heap: THeap; itsWmgrID: TWindowID; itsResizability: BOOLEAN)
                               : TWindow};
        VAR pWindow:    WindowPtr;
            panels:     TList;
            info:       WindowInfo;
    BEGIN
        {$IFC fTrace}BP(7);{$ENDC}
        IF object = NIL THEN
            object := NewObject(heap, THISCLASS);
        SELF := TWindow(object);

        GetWindInfo(WindowPtr(itsWmgrID), info);

        WITH SELF DO
            BEGIN
            panelTree := NIL;
            dialogBox := NIL;
            selectPanel := NIL;
            undoSelPanel := NIL;
            clickPanel := NIL;
            undoClickPanel := NIL;
            wmgrID := itsWmgrID;
            isResizable := itsResizability;
            believeWmgr := info.visible;
            changes := 0;
            selectWindow := SELF ;
            undoSelWindow := NIL; {+SW+}
            lastCmd := NIL;
            parentBranch := NIL;
            pgSzOK := TRUE;	  {client can explicitly set this to FALSE if bothered}
            pgRgOK := TRUE;	  {client can explicitly set this to FALSE if does own page-ranging}
            panelToPrint := NIL;
            objectToFree := NIL; {+SW+}
            END;

        panels := TList.CREATE(NIL, heap, 1);
        SELF.panels := panels;

        IF itsWmgrID = 0 THEN
            SELF.SetInnerRect(zeroRect)
        ELSE
            BEGIN
            pWindow := POINTER(itsWmgrID);
            SELF.SetInnerRect(pWindow^.portRect);
            END;

  {$H-} SELF.maxInnerSize := Point(FDiagRect(SELF.innerRect)); {$H+}
        {$IFC fTrace}EP;{$ENDC}
    END;
    {$S SgABCres}


    {$S SgABCini}
    PROCEDURE {TWindow.}Free;
    BEGIN
        {$IFC fTrace}BP(7);{$ENDC}
        Free(SELF.dialogBox);
        SELF.panels.Free;
        TArea.Free;
        {$IFC fTrace}EP;{$ENDC}
    END;
    {$S SgABCres}


    {$IFC fDebugMethods}
    {$S SgABCdbg}
    PROCEDURE {TWindow.}Fields{(PROCEDURE Field(nameAndType: S255))};
    BEGIN
        TArea.Fields(Field);
        Field('panels: TList');
        Field('panelTree: TArea');
        Field('dialogBox: TDialogBox');
        Field('selectPanel: TPanel');
        Field('undoSelPanel: TPanel');
        Field('clickPanel: TPanel');
        Field('undoClickPanel: TPanel');
        Field('selectWindow: TWindow');
        Field('undoSelWindow: TWindow');  {+SW+}
        Field('wmgrID: Ptr');
        Field('isResizable: BOOLEAN');
        Field('believeWmgr: BOOLEAN');
        Field('maxInnerSize: Point');
        Field('changes: LONGINT');
        Field('lastCmd: TCommand');
        Field(CONCAT('printerMetrics: RECORD paperRect: Rect; printRect: Rect;',
                      'res: Point; reserve: ARRAY[0..3] OF INTEGER END'));
        Field('pgSzOK: BOOLEAN');
        Field('pgRgOK: BOOLEAN');
        Field('panelToPrint: TPanel');
        Field('objectToFree: TObject');	 {+SW+}
        Field('');
    END;
    {$S SgABCres}
    {$ENDC}


{$S SgABCcld}
    PROCEDURE {TWindow.}AbortEvent;
    BEGIN
        {$IFC fTrace}BP(9);{$ENDC}
        {$IFC fTrace}EP;{$ENDC}
    END;
{$S SgABCres}


{$S SgABCpri}
    PROCEDURE {TWindow.}AcceptNewPrintingInfo{(document: TDocManager; prReserve: TPrReserve)};
     VAR  s:	    TListScanner;
          panel:    TPanel;
    BEGIN
        {$IFC fTrace}BP(9);{$ENDC}
        SELF.selectPanel.selection.MarkChanged;
        IF document = clipboard THEN	   {first, stuff the revised print record back in document}
            clipPrintPref := prReserve
        ELSE
            document.dataSegment.preludePtr^.printPref := prReserve;
        SELF.GetPrinterMetrics;
        s := SELF.panels.Scanner;
        WHILE s.Scan(panel) DO
            panel.currentView.ReactToPrinterChange;   {tell each view that printer style changed}
        {$IFC fTrace}EP;{$ENDC}
    END;
    {$S SgABCres}


    {$S sStartup}
    PROCEDURE {TWindow.}Activate; {assumes we are focused on the window already}
    BEGIN
        {$IFC fTrace}BP(7);{$ENDC}
        IF NOT SELF.believeWmgr THEN {is this needed????}
            SELF.Resize(FALSE);

        SELF.Update(TRUE);			  {force update in case just opened from an icon}
        currentWindow := SELF;

        {NOTE: currentDocument has already been set}
        activeWindowID := SELF.wmgrID;
        SELF.Refresh([rFrame], hDimToOn);
        IF currentDocument <> clipboard then
            SELF.ChkPrMismatch;
        SELF.PickStdCursor;
        clipboard.Inspect;
        IF SELF.dialogBox <> NIL THEN
            SELF.dialogBox.Appear;
        IF currentDocument.pendingNote <> 0 THEN
            BEGIN
            process.Note(currentDocument.pendingNote);
            currentDocument.pendingNote := 0;
            END;

        {reset undo}

        SELF.LoadMenuBar;
        menuBar.Draw;

        SetPt(clickState.where, -MAXINT, -MAXINT);
        {$IFC fTrace}EP;{$ENDC}
    END;
    {$S SgABCres}


    {$S Override}
    PROCEDURE {TWindow.}BlankStationery;
        VAR panel:  TPanel;
            view:   TView;
    BEGIN
        {$IFC fTrace}BP(7);{$ENDC}
        panel := TPanel.CREATE(NIL, SELF.Heap, SELF, 0, 0, [aScroll, aSplit], [aScroll, aSplit]);
        view := panel.NewStatusView(NIL, zeroLRect);
        {$IFC fTrace}EP;{$ENDC}
    END;
    {$S SgABCres}


    {$S sCommand}
    FUNCTION  {TWindow.}CanDoCommand{(cmdNumber: TCmdNumber; VAR checkIt: BOOLEAN): BOOLEAN};
    BEGIN
        {$IFC fTrace}BP(6);{$ENDC}
        CanDoCommand := currentWindow.CanDoStdCommand(cmdNumber, checkIt);
        {$IFC fTrace}EP;{$ENDC}
    END;


    {$S sCommand}
    FUNCTION  {TWindow.}CanDoStdCommand{(cmdNumber: TCmdNumber; VAR checkIt: BOOLEAN): BOOLEAN};
        VAR previewMode:    TPreviewMode;
            couldPrint:	    BOOLEAN;
            panelToUse:	    TPanel;
    BEGIN
        {$IFC fTrace}BP(6);{$ENDC}
        CanDoStdCommand := FALSE;

        couldPrint := (SELF.panelToPrint <> NIL);
        IF couldPrint THEN
            IF SELF.selectPanel.view.isPrintable THEN
                panelToUse := SELF.selectPanel
            ELSE
                panelToUse := SELF.panelToPrint;

        IF couldPrint THEN
            previewMode := panelToUse.previewMode;

        CASE cmdNumber OF

          {File/Print}

            uSetAllAside, uSetAside, uSetClipAside:
                CanDoStdCommand := TRUE;

            uPutAway, uRevertVersion:
                CanDoStdCommand := clipboard.window <> SELF;

            uSaveVersion:
                CanDoStdCommand := (clipboard.window <> SELF) AND
                                   (currentDocument.files.shouldToolSave OR
                                    NOT currentDocument.openedAsTool);

{$IFC LibraryVersion <= 20}
            uPrFmt, uPrint:
                CanDoStdCommand := onDesktop AND (SELF.dialogBox = NIL) AND couldPrint;
{$ELSEC}
            uPrFmt, uPrint, uPrintAsIs:
                CanDoStdCommand := onDesktop AND (SELF.dialogBox = NIL) AND couldPrint;
{$ENDC}

            uPrMonitor:
                CanDoStdCommand := onDesktop AND (SELF.dialogBox = NIL);        {**temporary**}

          {Edit}

            uUndoLast:
                IF SELF.lastCmd = NIL THEN
                    CanDoStdCommand := FALSE
                ELSE
                    CanDoStdCommand := SELF.lastCmd.undoable;

          {Page Layout}

            uPrvwMargins, uPrvwBreaks, uPrvwOff, uAddColumnStrip, uAddRowStrip:
                IF couldPrint THEN
                    BEGIN
                    CanDoStdCommand := TRUE;  {or they wouldnt've been in the phrase file}
                    CASE cmdNumber OF
                        uPrvwMargins:
                            checkIt := previewMode = mPrvwMargins;
                        uPrvwBreaks:
                            checkIt := previewMode = mPrvwBreaks;
                        uPrvwOff:
                            checkIt := previewMode = mPrvwOff;
                        END;
                    END;

            uDesignPages:
                IF couldPrint THEN
                    BEGIN
                    CanDoStdCommand := (SELF.dialogBox = NIL);
                    checkIt := (SELF.dialogBox = panelToUse.view.printManager.layoutDialogBox)
                                    AND (SELF.dialogBox <> NIL);
                    END;

            uSetHorzBreak, uSetVertBreak, uClearBreaks:
                CanDoStdCommand := SELF.clickPanel.view.isPrintable;

            uShowFullSize, uReduce70Pct, uReduceToFit:
                CanDoStdCommand := fExperimenting;					   {**temporary**}

            uRiseVertically, uRiseHorizontally:
                IF couldPrint THEN
                    BEGIN
                    CanDoStdCommand := TRUE;
                    checkIt := panelToUse.view.printManager.pageRiseDirection =
                                                            VHSelect(cmdNumber = uRiseHorizontally);
                    END
                ELSE
                    CanDoStdCommand := FALSE;

          {$IFC fDbgABC}
          {Debug}

            uReportEvents, uCountHeap, uCheckIndices,
              uExperimenting, uDumpGlobals, uDumpPrelude,
              uMainScramble, uDocScramble:
                BEGIN
                CanDoStdCommand := TRUE;
                CASE cmdNumber OF
                    uReportEvents:
                        checkIt := eventDebug;
                    uCountHeap:
                        checkIt := fCountHeap;
                    uCheckIndices:
                        checkIt := fCheckIndices;
                    uExperimenting:
                        checkIt := fExperimenting;
                    uMainScramble:
                        checkIt := THz(mainHeap)^.fScramble;
                    uDocScramble:
                        IF currentDocument <> NIL THEN
                            checkIt := THz(currentDocument.docHeap)^.fScramble
                        ELSE
                            CanDoStdCommand := FALSE;
                    END;
                END;

            uReptGarbage, uFreeGarbage:				        {Debug}
                CanDoStdCommand := clipboard.window <> SELF;
          {$ENDC}

            END;
        {$IFC fTrace}EP;{$ENDC}
    END;
{$S SgABCres}


    {$S sStartup}
    PROCEDURE {TWindow.}ChkPrMismatch;
        VAR styleDidChange: BOOLEAN;
            prPrfAlias:	    TPrPrfAlias;
            s:		    TListScanner;
            panel:	    TPanel;
            error:	    INTEGER;
            document:	    TDocManager;
    BEGIN
        {$IFC fTrace}BP(7);{$ENDC}
        IF currentDocument <> NIL THEN
            document := currentDocument
        ELSE
            document := boundDocument;
        IF document = clipboard THEN
            prPrfAlias.reserve := clipPrintPref
        ELSE
            prPrfAlias.reserve := document.dataSegment.preludePtr^.PrintPref;
{$IFC libraryVersion <= 20}	    { P E P S I }
        IF FPrArbRqd(prPrfAlias.prPrf) THEN
            BEGIN
            PrArbDlg(error, prPrfAlias.prPrf, styleDidChange);
{$ELSEC}			    { S P R I N G }
        IF NOT fPrPrfValid(prPrfAlias.prPrf) THEN
            BEGIN
            PrPrfDlg(prPrfAlias.prPrf, styleDidChange, NOT SELF.pgSzOK);
{$ENDC}

            IF styleDidChange THEN
                SELF.AcceptNewPrintingInfo(document, prPrfAlias.reserve);
            END;
        {?? Do we need to worry about refreshing the window when needed?}
        {$IFC fTrace}EP;{$ENDC}
    END;


    {$S sCommand}
    PROCEDURE {TWindow.}CommitLast;
        VAR lastCmd:    TCommand;
            lastView:   TView; {+SW+}
            selection:  TSelection; {+SW+}
    BEGIN
        {$IFC fTrace}BP(7);{$ENDC}
        IF SELF <> currentWindow THEN
            currentWindow.CommitLast
        ELSE
            BEGIN
            lastCmd := SELF.lastCmd;
            IF lastCmd <> NIL THEN
                BEGIN
                IF lastCmd.doing THEN
                    lastCmd.Commit;
(*****
                IF lastCmd.image <> NIL THEN
                    BEGIN
                    lastView := lastCmd.image.view;
                    selection := lastView.panel.undoSelection.FreedAndReplacedBy(lastView.NoSelection);
                    END;
*****)
                lastCmd.Free;
                SELF.lastCmd := NIL;
                END;
            END;
        {$IFC fTrace}EP;{$ENDC}
    END;


    {$S sStartup}
    FUNCTION  {TWindow.}CursorFeedback{: TCursorNumber};
        VAR s:		    TListScanner;
            panel:	    TPanel;
            cursorNumber:   TCursorNumber;
            mousePt:	    Point;
    BEGIN
        {$IFC fTrace}BP(3);{$ENDC}
        PushFocus;
        SELF.Focus;
        cursorNumber := noCursor;
        GetMouse(mousePt);
        IF RectHasPt(SELF.innerRect, mousePt) THEN
            IF SELF.isResizable AND fGrowHit(mousePt) THEN
                cursorNumber := arrowCursor
            ELSE
                BEGIN
                s := SELF.panels.Scanner;
                WHILE s.Scan(panel) DO
                    BEGIN
                    cursorNumber := panel.CursorAt(mousePt);
                    IF cursorNumber <> noCursor THEN
                        s.Done;
                    END;
                IF cursorNumber = noCursor THEN
                    cursorNumber := arrowCursor;
                END;
        PopFocus;
        CursorFeedback := cursorNumber;
        {$IFC fTrace}EP;{$ENDC}
    END;


    {$S SgABCcld}
    PROCEDURE {TWindow.}Deactivate; {assumes we are focused on the window already}
    BEGIN
        {$IFC fTrace}BP(7);{$ENDC}
(******************** these lines are needed for the Extra Window feature *)
        IF currentWindow <> SELF THEN
            BEGIN
            GiveControl(event); {This must be last}
            {$IFC fTrace}EP;{$ENDC}
            EXIT(Deactivate);
            END;
(* ********************)
        SELF.CommitLast;

        IF SELF.dialogBox <> NIL THEN
            SELF.dialogBox.Disappear;

        activeWindowID := 0; {must precede StashPicture and Refresh so scroll bars are white}
        SELF.Refresh([rFrame], hOnToDim); {do first to give user feedback}
        SELF.StashPicture(hOfftoDim);
        IF (SELF.wmgrId <> ORD(scrapFolder)) AND (event.fromProcess <> myProcessID) THEN
            clipboard.Publicize;

        focusArea := NIL;

        IF NOT inBackground THEN
            currentDocument.Deactivate;

        GiveControl(event); {This must be last}
        {$IFC fTrace}EP;{$ENDC}
    END;
    {$S SgABCres}


    {$S sCommand}
    PROCEDURE {TWindow.}DoCommand{(cmdNumber: TCmdNumber)};
        VAR command: TCommand;
    BEGIN
        {$IFC fTrace}BP(7);{$ENDC}
        IF cmdNumber <> 0 THEN
            BEGIN
            IF cmdNumber = uUndoLast THEN
                SELF.UndoLast
            ELSE
                BEGIN
                command := SELF.selectPanel.selection.NewCommand(cmdNumber);
                IF command <> NIL THEN	    {NOTE: If NewCommand Frees SELF (this window), it MUST return NIL}
                    SELF.PerformCommand(command);
                END;
            process.RememberCommand(cmdNumber);
            END;
        menuBar.EndCmd;
        {$IFC fTrace}EP;{$ENDC}
    END;


    {$S sClick}
    FUNCTION  {TWindow.}DownAt{(mousePt: Point): BOOLEAN};
        VAR s:	    TListScanner;
            panel:  TPanel;
            b:	    BOOLEAN;
    BEGIN
        {$IFC fTrace}BP(7);{$ENDC}
        b := FALSE;
        IF RectHasPt(SELF.innerRect, mousePt) THEN
            BEGIN
            IF SELF.isResizable THEN
                IF fGrowHit(mousePt) THEN
                    BEGIN
                    SELF.DownInSizeBox(mousePt);
                    b := TRUE;
                    process.RememberCommand(uResizeWindow);
                    END;
            IF NOT b THEN
                BEGIN
                b := TRUE;
                s := SELF.panels.Scanner;
                WHILE s.Scan(panel) DO
                    IF panel.DownAt(mousePt) THEN
                        s.Done;
                END;
            END;
        DownAt := b;
        {$IFC fTrace}EP;{$ENDC}
    END;


    {$S sClick}
    PROCEDURE {TWindow.}DownEventAt{(mousePt: Point)};
    VAR clickNeighborhood:  Rect;
    BEGIN
        {$IFC fTrace}BP(7);{$ENDC}
        SELF.Update(TRUE);  {In case an alert box was dismissed by the click}

            { given that previous click was at (0,0), clickNeighborhood is a rectangle in which
                this click must fall for it to have a chance at being a double click }
        SetRect(clickNeighborhood, -9, -6, 9, 6);   { clickNeighborhood should be a method call;
                                                        how much flexibility is needed???? }

        IF ((event.when - clickState.when) < clickDelay) AND
           (RectHasPt(clickNeighborhood, Point(FPtMinusPt(event.where, clickState.where)))) THEN
            clickState.clickCount := Min(clickState.clickCount + 1, 3)
        ELSE
            BEGIN
            clickState.clickCount := 1;
            clickState.fShift := event.shiftKey;
            clickState.fOption := event.codeKey;
            clickState.fApple := event.appleKey;
            END;
        clickState.when := event.when;
        clickState.where := event.where;
        IF SELF.DownAt(mousePt) THEN;
        {$IFC fTrace}EP;{$ENDC}
    END;


    {$S sClick}
    PROCEDURE {TWindow.}DownInSizeBox{(mousePt: Point)};
        VAR oldRect:	    Rect;
            fullRect:	    Rect;   {includes title tab}
            minExtent:	    Point;
            minBotRight:    Point;
            maxBotRight:    Point;
            savePort:	    GrafPtr;
            newBotRight:    Point;
    BEGIN
        {$IFC fTrace}BP(7);{$ENDC}
        oldRect := SELF.innerRect;

        SELF.GetMinExtent(minExtent, TRUE);
        minBotRight := Point(FPtPlusPt(oldRect.topLeft, minExtent));

        LocalToGlobal(minBotRight);
        LocalToGlobal(mousePt);
        LocalToGlobal(oldRect.topLeft);
        LocalToGlobal(oldRect.botRight);
        maxBotRight := Point(FPtMaxPt(minBotRight, screenBits.bounds.botRight));

        fullRect := oldRect;
        fullRect.top := fullRect.top - dvSBox; {allow for title tab}

        GetPort(savePort);
        SetPort(deskPort);
        ResizeFeedback(mousePt, minBotRight, maxBotRight, fullRect, dvSBox, dhSBox, dvSBox, newBotRight);
        SetPort(savePort);

        SELF.ResizeTo(Point(FPtMinusPt(newBotRight, oldRect.topLeft)));
        {$IFC fTrace}EP;{$ENDC}
    END;


    {$S sFilter}  {+SW+}
    PROCEDURE {TWindow.}EachActualPart{(PROCEDURE DoToObject(filteredObj: TObject))};
        VAR n:	        INTEGER;
            cmdWindow:  TWindow;
    BEGIN
        {$IFC fTrace}BP(11);{$ENDC}
        {$IFC fDbgABC}
        IF SELF = currentWindow.dialogBox THEN
            cmdWindow := currentWindow
        ELSE
            cmdWindow := SELF;

        IF cmdWindow.lastCmd = NIL THEN
            n := 0
        ELSE
            n := cmdWindow.lastCmd.cmdNumber;
        ABCBreak('A View or Window tried to filter but did not implement EachActualPart: lastCmd =', n);
        {$ENDC}
        {$IFC fTrace}EP;{$ENDC}
    END;
    {$S SgABCres}


    {$S sFilter}
    PROCEDURE {TWindow.}EachVirtualPart{(PROCEDURE DoToObject(filteredObj: TObject))};
    BEGIN
        {$IFC fTrace}BP(11);{$ENDC}
        SELF.FilterDispatch(NIL, NIL, DoToObject);
        {$IFC fTrace}EP;{$ENDC}
    END;


    {$S sFilter}
    PROCEDURE {TWindow.}FilterAndDo{(actualObj: TObject; PROCEDURE DoToObject(filteredObj: TObject))};
    BEGIN
        {$IFC fTrace}BP(11);{$ENDC}
        SELF.FilterDispatch(actualObj, NIL, DoToObject);
        {$IFC fTrace}EP;{$ENDC}
    END;


    {$S sFilter}
    PROCEDURE {TWindow.}FilterDispatch{(actualObj: TObject; image: TImage;
                                        PROCEDURE DoToObject(filteredObj: TObject))};
    VAR filterCommand:  TCommand;
        filtering:      BOOLEAN;
        cmdWindow:      TWindow;
    BEGIN
        {$IFC fTrace}BP(11);{$ENDC}
        cmdWindow := SELF;
        IF currentWindow <> NIL THEN
            IF SELF = currentWindow.dialogBox THEN
                cmdWindow := currentWindow;

        filterCommand := cmdWindow.lastCmd;

        filtering := FALSE;
        IF filterCommand <> NIL THEN
            IF filterCommand.doing THEN
                IF filterCommand.image <> NIL THEN
                    filtering := filterCommand.image.SeesSameAs(image);

        IF filtering THEN
            IF actualObj <> NIL THEN
                filterCommand.FilterAndDo(actualObj, DoToObject)
            ELSE
                filterCommand.EachVirtualPart(DoToObject)
        ELSE
        IF actualObj <> NIL THEN
            DoToObject(actualObj)
        ELSE
        IF image <> NIL THEN
            image.EachActualPart(DoToObject)
        ELSE
            SELF.EachActualPart(DoToObject);
        {$IFC fTrace}EP;{$ENDC}
    END;


{$S sStartup}
    PROCEDURE {TWindow.}Focus;
    BEGIN
        {$IFC fTrace}BP(6);{$ENDC}
        SetPort(POINTER(SELF.wmgrID));
        SetOrigin(0, 0);
        ClipRect(thePort^.portRect);
        IF useAltVisRgn THEN
            focusRgn := altVisRgn       {Instigated by TWindow.StashPicture or TClipboard.Publicize}
        ELSE
            focusRgn := thePort^.visRgn;
        focusArea := SELF;
        {$IFC fTrace}EP;{$ENDC}
    END;
{$S SgABCres}


{$S sStartup}
    PROCEDURE {TWindow.}Frame;
        VAR growRect: Rect;
    BEGIN
        {$IFC fTrace}BP(6);{$ENDC}
        IF SELF.isResizable THEN
            BEGIN
            GetGrowRect(growRect);
            IF RectIsVisible(growRect) THEN
                IF SELF.IsActive THEN
                    PaintGrow
                ELSE
                    FillRect(growRect, white);
            END;
        {$IFC fTrace}EP;{$ENDC}
    END;
{$S SgABCres}


    {$S sCldInit}
    PROCEDURE {TWindow.}GetPrinterMetrics;
         VAR  prPrfAlias:   TPrPrfAlias;
              prInfo:	    TPrInfo;
              tkDevice:	    INTEGER;
              document:	    TDocManager;
    BEGIN
        {$IFC fTrace}BP(9);{$ENDC}
        IF currentDocument <> NIL THEN
            document := currentDocument
        ELSE
            document := boundDocument;
        IF document = clipboard THEN
            prPrfAlias.reserve := clipPrintPref
        ELSE
            prPrfAlias.reserve := document.dataSegment.preludePtr^.printPref;
{$IFC libraryVersion <= 20}	    { P E P S I }
        PrMetrics(prPrfAlias.prPrf, prInfo);
{$ELSEC}			    { S P R I N G }
        prInfo := prPrfAlias.prPrf.prInfo;  {this looks odd, but the prPrf is of type prRec really}
{$ENDC}
        WITH SELF.printerMetrics, prInfo DO
            BEGIN
            printRect := rPrintable;
            paperRect := rPaper;
            END;
        SELF.printerMetrics.res.h := prInfo.hRes;
        SELF.printerMetrics.res.v := prInfo.vRes;
        {$IFC fTrace}EP;{$ENDC}
    END;
    {$S SgABCres}


    {$S sStartup}
    PROCEDURE {TWindow.}GetMinExtent{(VAR minExtent: Point; windowIsResizingIt: BOOLEAN)};
    BEGIN
        {$IFC fTrace}BP(9);{$ENDC}
        SELF.panelTree.GetMinExtent(minExtent, windowIsResizingIt);
        {$IFC fTrace}EP;{$ENDC}
    END;
    {$S SgABCres}


    {$S sRes}
    PROCEDURE {TWindow.}GetTitle{(VAR title: S255)};
        VAR kludge: Str255;
    BEGIN
        {$IFC fTrace}BP(7);{$ENDC}
        GetFldrTitle(POINTER(SELF.wmgrID), kludge);
        title := kludge;
        {$IFC fTrace}EP;{$ENDC}
    END;


    {$S sStartup}
    PROCEDURE {TWindow.}Highlight{(highTransit: THighTransit)};
        PROCEDURE HilitePanel(obj: TObject);
        BEGIN
            TPanel(obj).Highlight(TPanel(obj).selection, highTransit);
        END;
    BEGIN
        {$IFC fTrace}BP(7);{$ENDC}
        SELF.panels.Each(HilitePanel);
        {$IFC fTrace}EP;{$ENDC}
    END;
{$S SgABCres}


    {$S sRes}
    PROCEDURE {TWindow.}IdleBegin{(centiSeconds: LONGINT)};
    BEGIN
        {$IFC fTrace}BP(7);{$ENDC}
        LetOthersRun;
        {$IFC fTrace}EP;{$ENDC}
    END;


    {$S sRes}
    PROCEDURE {TWindow.}IdleContinue{(centiSeconds: LONGINT)};
    BEGIN
        {$IFC fTrace}BP(5);{$ENDC}
        IF SELF.IsActive THEN
            process.TrackCursor;
        LetOthersRun;
        {$IFC fTrace}EP;{$ENDC}
    END;


    {$S sRes}
    PROCEDURE {TWindow.}IdleEnd{(centiSeconds: LONGINT)};
    BEGIN
        {$IFC fTrace}BP(7);{$ENDC}
        {$IFC fTrace}EP;{$ENDC}
    END;


    {$S sStartup}
    FUNCTION  {TWindow.}IsActive{: BOOLEAN};
    BEGIN
        {$IFC fTrace}BP(3);{$ENDC}
        IF activeWindowID = 0 THEN  {nothing is active}
            IsActive := FALSE
        ELSE IF currentWindow = NIL THEN
            BEGIN
            IsActive := FALSE;
            {$IFC fDbgABC}
            Writeln(CHR(7), '********************');
            Writeln('In TWindow.IsActive, activeWindowID <> 0 AND currentWindow = NIL');
            Writeln('activeWindowID=', activeWindowID:1, '   currentWindow=', ORD(currentWindow):1);
            Writeln('********************');
            {$ENDC}
            END
        ELSE
            IsActive := (SELF.wmgrID = activeWindowID) OR (SELF.wmgrID = ORD(dialogFolder));
        {$IFC fTrace}EP;{$ENDC}
    END;


    {$S sStartup}
    FUNCTION  {TWindow.}IsVisible{: BOOLEAN};
        VAR info:   WindowInfo;
    BEGIN
        {$IFC fTrace}BP(3);{$ENDC}
        GetWindInfo(WindowPtr(SELF.wmgrID), info);
        IsVisible := info.visible;
        {$IFC fTrace}EP;{$ENDC}
    END;
    {$S SgABCres}


    {$S sStartup}
    PROCEDURE {TWindow.}LoadMenuBar;
        VAR i:		    INTEGER;
            menuID:	    INTEGER;
            inClipboard:    BOOLEAN;
    BEGIN
        {$IFC fTrace}BP(7);{$ENDC}
        inClipboard := activeWindowID = ORD(scrapFolder);

        FOR i := 1 TO menuBar.numMenus DO
            BEGIN
            menuID := wmgrMenus[i].menuID;
            IF SELF.WantMenu(menuID, inClipboard) THEN
                menuBar.Insert(menuID, 0);
            END;
        {$IFC fTrace}EP;{$ENDC}
    END;
    {$S SgABCres}


    {$S sRes}
    PROCEDURE {TWindow.}MenuEventAt{(mousePt: Point)};
        VAR cmdNumber: TCmdNumber;
    BEGIN
        {$IFC fTrace}BP(7);{$ENDC}
        SELF.SetupMenus;
        cmdNumber := menuBar.DownAt(mousePt);
        IF SELF.selectPanel = NIL THEN
            {$IFC fDbgABC} ABCBreak('ObeyTheEvent: selectPanel=NIL', 0) {$ENDC}
        ELSE
            SELF.DoCommand(cmdNumber);
        {$IFC fTrace}EP;{$ENDC}
    END;


{$IFC LibraryVersion > 20}
{$S SgABCcld}
    PROCEDURE {TWindow.}NameToPrefix(VAR error, offset: INTEGER; VAR name, prefix: TFilePath);
    BEGIN
        {$IFC fTrace}BP(7);{$ENDC}
        NameToPrefix(error, offset, WindowPtr(SELF.wmgrID), Pathname(name), Pathname(prefix));
        {$IFC fTrace}EP;{$ENDC}
    END;
{$S SgABCres}
{$ENDC}


    {$S sCommand}
    FUNCTION  {TWindow.}NewCommand{(cmdNumber: TCmdNumber): TCommand};
    BEGIN
        {$IFC fTrace}BP(7);{$ENDC}
        NewCommand := currentWindow.NewStdCommand(cmdNumber);
        {$IFC fTrace}EP;{$ENDC}
    END;


    {$S sCommand}
    FUNCTION  {TWindow.}NewStdCommand{(cmdNumber: TCmdNumber): TCommand};
    VAR document:       TDocManager;
        didStyleChange: BOOLEAN;
{$IFC LibraryVersion <= 20}
        prPrf:	        TPrPrf;
{$ENDC}
        prPrfAlias:     TprPrfAlias;
        shouldPrint:    BOOLEAN;
        error:	        INTEGER;
        str:	        S255;
        permCmd:        BOOLEAN;    { TRUE iff the command is a permanent one }
        command:        TCommand;
        s:	        TListScanner;
        panel:	        TPanel;
        zoomNum:        Point;
        zoomDen:        Point;
        selectPanel:    TPanel;
        clickPanel:     TPanel;
        selection:      TSelection;
        vhs:	        VHSelect;
        andContinue:    BOOLEAN;
        excessBytes:    INTEGER;
        printManager:   TPrintManager;
        panelToUse:     TPanel;

        FUNCTION  RevertConfirmed: BOOLEAN;
            VAR s:	    TParamAlert;
                ph:	    INTEGER;
{$IFC LibraryVersion <= 20}
                info:	    fs_info;
{$ELSEC}
                info:	    Q_Info;
{$ENDC}
                osErr:	    INTEGER;
                pPath:	    ^Pathname;
                osDT:	    LONGINT;
        BEGIN
            RevertConfirmed := FALSE;

            IF SELF.changes = 0 THEN
                process.Note(phUnchanged)

            ELSE
                BEGIN
                IF document.files.saveExists THEN
                    BEGIN
                    pPath := @document.files.volumePrefix;
{$IFC LibraryVersion <= 20}
                    Lookup(osErr, pPath^, info);
{$ELSEC}
                    Quick_Lookup(osErr, pPath^, info);
{$ENDC}
                    IF osErr <= 0 THEN
                        osDT := info.DTM
                    ELSE
                        osDT := -1;
                    {$IFC LibraryVersion < 13}
                    DTAlert(osDT, s);
                    {$ELSEC}
                    DTAlert(alerts, osDT, s);
                    {$ENDC}
                    process.ArgAlert(1, s);
                    ph := phRevert;
                    END
                ELSE
                    ph := phRevBlank;

                IF process.Caution(ph) THEN
                    RevertConfirmed := TRUE;
                END;
        END;
    BEGIN
        {$IFC fTrace}BP(7);{$ENDC}
        document := currentDocument;
        {$IFC fDbgABC}
        IF SELF.wmgrID <> document.window.wmgrID THEN
            ABCbreak('In TWindow.NewStdCommand: SELF.wmgrID <> document.window.wmgrID; document=',
                        ORD(document));
        {$ENDC}
        selectPanel := SELF.selectPanel;
        clickPanel := SELF.clickPanel;
        selection := selectPanel.selection;

        IF selectPanel.view.isPrintable THEN
            panelToUse := selectPanel
        ELSE
            panelToUse := SELF.panelToPrint;
        error := 0;
        NewStdCommand := NIL; {the default return value}
        permCmd := FALSE; {if set to TRUE, make a permanent command object}
        allowAbort := TRUE; {??? should we assume this ???}

        CASE cmdNumber OF

           {File/Print Menu}
            uSetAllAside:
                BEGIN
                SELF.CommitLast;
                DoFilingCmd(cmdClosAll);
                permCmd := TRUE;
                END;
            uSetAside, uSetClipAside:
                BEGIN
                SELF.CommitLast;
                DoFilingCmd(cmdClose);
                permCmd := TRUE;
                END;
            uPutAway, uSaveVersion: {must be the active window to do this}
                BEGIN
                andContinue := cmdNumber = uSaveVersion;

                SELF.CommitLast;
                IF andContinue THEN
                    excessBytes := docExcess
                ELSE
                    excessBytes := 0;
                document.ConserveMemory(excessBytes, TRUE {do GC});

                IF (document.window.changes <> 0) AND
                   (document.files.shouldToolSave OR NOT document.openedAsTool) THEN
                    BEGIN
                    process.BeginWait(phSaving);
                    document.SaveVersion(error, document.files.volumePrefix, andContinue);
                    process.EndWait;
                    END
                ELSE IF andContinue THEN
                    process.Note(phUnchanged);
                {shouldn't we put up a message on Save & Put Away even if document is unchanged???}

                IF (error <= 0) AND NOT andContinue THEN      {*** some cases worse! ***}
                    BEGIN
                    TellFiler(error, docClosd, docPutBack, POINTER(activeWindowID));
                    IF error > 0 THEN
                        BEGIN
                        ABCBreak('TellFiler', error);
                        error := 0;
                        END;
                    closedDocument := document;
                    closedBySuspend := FALSE;
                    END;

                {do something if there was an error}
                IF error = erAborted THEN
                    process.Stop(phTerminated)
                ELSE IF error > 0 THEN
                    process.Stop(phCantSave);

                error := 0; {we already put up the alert}
                permCmd := TRUE;
                END;
            uRevertVersion:
                IF RevertConfirmed THEN
                    BEGIN
                    document.RevertVersion(error, activeWindowID);
                    {do something if there was an error}
                    IF error = erAborted THEN
                        process.Stop(phTerminated)
                    ELSE IF error > 0 THEN
                        BEGIN
                        process.Stop(phCantRevert);
                        process.Complete(FALSE); {nothing else to do: we unbound out data segments}
                        END;

                    error := 0; {we already put up the alert}
                    permCmd := TRUE; {no need to CommitLast}
                    END;      {long-standing commented-out code now out}
            uPrFmt:
                BEGIN
                IF document = clipboard THEN
                    prPrfAlias.reserve := clipPrintPref
                ELSE
                    prPrfAlias.reserve := document.dataSegment.preludePtr^.printPref;
                PushFocus;
{$IFC libraryVersion <= 20}	    { P E P S I }
                PrPrfDlg(error, prPrfAlias.prPrf, didStyleChange);
{$ELSEC}			    { S P R I N G }
                PrPrfDlg(prPrfAlias.prPrf, didStyleChange, NOT SELF.pgSzOK);
{$ENDC}
                PopFocus;
                IF didStyleChange THEN
                    BEGIN
                    SELF.AcceptNewPrintingInfo(document, prPrfAlias.reserve);
                    permCmd := TRUE;
                    END;
                END;

            uPrint:
                SELF.Print(panelToUse, NOT SELF.pgRgOK, FALSE {put up dialog} );

            uPrintAsIs:
                SELF.Print(panelToUse, TRUE {suppress page range}, TRUE {suppress dialog});

            uPrMonitor:
                BEGIN
                PushFocus;
{$IFC libraryVersion <= 20}	    { P E P S I }
                PrBgdDlg(error, TRUE);
{$ELSEC}			    { S P R I N G }
                PrBgdDlg;
{$ENDC}
                PopFocus;
                END;

           {Zooming & previewing pages}	     {some or all of these must become command objects}
            uPrvwMargins:
                panelToUse.Preview(mPrvwMargins);

            uPrvwBreaks:
                panelToUse.Preview(mPrvwBreaks);

            uPrvwOff:
                panelToUse.Preview(mPrvwOff);

            uDesignPages:
                BEGIN
                printManager := panelToUse.view.printManager;
                IF printManager <> NIL THEN
                    printManager.EnterPageEdit;
                END;

            uRiseVertically,
                uRiseHorizontally:
                    BEGIN
                    IF cmdNumber = uRiseVertically THEN
                        panelToUse.view.printManager.pageRiseDirection := v
                    ELSE
                        panelToUse.view.printManager.pageRiseDirection := h;
                    IF panelToUse.previewMode = mPrvwMargins THEN
                        panelToUse.Invalidate;
                    END;

            uAddColumnStrip,
                uAddRowStrip:
                    BEGIN
                    IF cmdNumber = uAddColumnStrip THEN
                        vhs := v
                    ELSE
                        vhs := h;
                    panelToUse.currentView.AddStripOfPages(vhs);
                    END;

            uShowFullSize:
                BEGIN
                SetPt(zoomNum, 1, 1);
                selectPanel.SetZoomFactor(zoomNum, zoomNum);   {++ should this be panelToUse?? ++}
                selectPanel.Invalidate;
                END;

            uReduce70Pct:
                BEGIN
                WITH selectPanel.zoomFactor DO
                    IF numerator.h = 1 THEN
                        BEGIN
                            zoomNum.h := 7;
                            zoomDen.h := denominator.h * 10;
                            zoomNum.v := 7;
                            zoomDen.v := denominator.v * 10;
                        END
                    ELSE {numerator not 1, must be 7}
                        BEGIN
                            zoomNum.h := 1;
                            zoomDen.h := denominator.h DIV 5;
                            zoomNum.v := 1;
                            zoomDen.v := denominator.v DIV 5;
                        END;
                selectPanel.SetZoomFactor(zoomNum, zoomDen);
                selectPanel.Invalidate;
                END;

            uReduceToFit:
                {?} {can't do it now--how to express?} ;

            uSetHorzBreak:
                IF clickPanel.view.isPrintable THEN
                    BEGIN
                    clickPanel.view.printManager.SetBreak(h, clickPanel.view.clickLPt.v, FALSE);
                    clickPanel.currentView.ReDoBreaks;
                    clickPanel.Invalidate;
                    END;

            uSetVertBreak:
                IF clickPanel.view.isPrintable THEN
                    BEGIN
                    clickPanel.view.printManager.SetBreak(v, clickPanel.view.clickLPt.h, FALSE);
                    clickPanel.currentView.ReDoBreaks;
                    clickPanel.Invalidate;  {later, do a more selective inval}
                    END;

            uClearBreaks:
                IF clickPanel.view.isPrintable THEN
                    BEGIN
                    clickPanel.view.printManager.ClearPageBreaks(FALSE);
                    clickPanel.currentView.ReDoBreaks;
                    clickPanel.Invalidate;  {later, do a more selective inval}
                    END;

            {$IFC fDbgABC}
            {Debug Menu}
            uReportEvents:
                SELF.ToggleFlag(eventDebug);
            uCountHeap:
                SELF.ToggleFlag(fCountHeap);
            uCheckIndices:
                SELF.ToggleFlag(fCheckIndices);
            uDumpGlobals:				        {dump process variables}
                process.DumpGlobals;
            uDumpPrelude:				        {dump active document's prelude}
                document.DumpPrelude;
            uExperimenting:
                SELF.ToggleFlag(fExperimenting);
            uReptGarbage, uFreeGarbage:
                IF document <> clipboard THEN
                    BEGIN
                    MarkHeap(document.docHeap, ORD(document.dataSegment.preludePtr^.docDirectory));
                    SweepHeap(document.docHeap, cmdNumber = uReptGarbage);
                    END;
            uMainScramble:
                THz(mainHeap)^.fScramble := NOT THz(mainHeap)^.fScramble;
            uDocScramble:
                IF currentDocument <> NIL THEN
                    THz(currentDocument.docHeap)^.fScramble :=
                        NOT THz(currentDocument.docHeap)^.fScramble;
            {$ENDC}

            OTHERWISE
                BEGIN
                IF menuBar.GetCmdName(cmdNumber, @str) THEN
                    process.ArgAlert(1, str)
                ELSE
                    BEGIN
                    {$IFC fDbgABC}
                    ABCbreak('called new command, but no command in menu', cmdNumber);
                    {$ENDC}
                    process.ArgAlert(1, 'Unknown Command');
                    END;

                IF selection.kind = nothingKind THEN
                    process.Stop(phNoSel)
                ELSE
                    process.Stop(phUnkCmd);
                END;
            END;

        IF permCmd THEN
            BEGIN
            command := TCommand.CREATE(NIL, SELF.Heap, cmdNumber, NIL, FALSE, revealNone);
            WITH command DO
                BEGIN
                unHiliteBefore[doPhase] := FALSE;
                hiliteAfter[doPhase] := FALSE;
                END;
            NewStdCommand := command;
            END;

        IF error > 0 THEN
            process.Stop(process.Phrase(error));
        {$IFC fTrace}EP;{$ENDC}
    END;
    {$S SgABCres}


    {$S sCommand}
    PROCEDURE {TWindow.}PerformCommand{(newCommand: TCommand)};
    BEGIN
        {$IFC fTrace}BP(7);{$ENDC}
        IF newCommand <> NIL THEN {this is a command that changes the document}
            BEGIN
            {commit the previous command}
            SELF.CommitLast;

            {save the new command & get rid of the old one}
            SELF.SaveCommand(newCommand);

            {execute the new command}
            SELF.PerformLast(doPhase);
            END;
        {$IFC fTrace}EP;{$ENDC}
    END;
    {$S SgABCres}


    {$S sCommand}
    PROCEDURE {TWindow.}PerformLast{(cmdPhase: TCmdPhase)};  {+SW+} {LSR: Your version below, commented out}
    VAR image:	    TImage;
        lastCmd:    TCommand;
        lastWindow: TWindow;
    BEGIN
        {$IFC fTrace}BP(7);{$ENDC}
        IF SELF <> currentWindow THEN
            currentWindow.PerformLast(cmdPhase)
        ELSE
            BEGIN
            lastCmd := SELF.lastCmd;
            image := lastCmd.image;
            IF image = NIL THEN
                lastWindow := SELF
            ELSE
                lastWindow := image.view.panel.window; {+SW+}

            {UnHighlight all selections before performing the command (unless command object says otherwise)}
            IF lastCmd.unHiliteBefore[cmdPhase] THEN
                currentWindow.selectWindow.Highlight(hOnToOff);	 {+sw+}

            IF cmdPhase <> doPhase THEN
                lastWindow.RestoreSelection;{+sw+}

            IF lastCmd.revelation <> revealNone THEN
                lastWindow.RevealSelection(lastCmd.revelation = revealAll,
                                           NOT lastCmd.unHiliteBefore[cmdPhase]);

            lastWindow.selectPanel.selection.PerformCommand(lastCmd, cmdPhase);	 {+sw+}

            {Save selection in each panel; hilite if necessary}
            SELF.SaveSelection;

            IF NOT deferUpdate THEN
                IF lastCmd.HiliteAfter[cmdPhase] THEN
                    BEGIN
                    lastWindow.Update(FALSE);{+sw+}
                    lastWindow.Highlight(hOffToOn);{+sw+}
                    END
                ELSE
                    lastWindow.Update(TRUE);{+sw+}
            END;
        {$IFC fTrace}EP;{$ENDC}
    END;


(*  PROCEDURE {TWindow.}PerformLast{(cmdPhase: TCmdPhase)};
    VAR lastCmd:    TCommand;

        PROCEDURE PerformIt;
            BEGIN
            {UnHighlight all selections before performing the command (unless command object says otherwise)}
            IF lastCmd.unHiliteBefore[cmdPhase] THEN
                SELF.Highlight(hOnToOff);

            IF cmdPhase <> doPhase THEN
                SELF.RestoreSelection;

            IF lastCmd.revelation <> revealNone THEN
                SELF.RevealSelection(lastCmd.revelation = revealAll, NOT lastCmd.unHiliteBefore[cmdPhase]);

            lastCmd.doing := cmdPhase <> undoPhase;
            lastCmd.Perform(cmdPhase);

            {Save selection in each panel; hilite if necessary}
            SELF.SaveSelection;

            IF lastCmd.HiliteAfter[cmdPhase] THEN
                BEGIN
                SELF.Update(FALSE);
                SELF.Highlight(hOffToOn);
                END
            ELSE
                SELF.Update(TRUE);
        END;

    BEGIN
        {$IFC fTrace}BP(7);{$ENDC}
        IF SELF <> currentWindow THEN
            currentWindow.PerformLast(cmdPhase)
        ELSE
            BEGIN
            lastCmd := SELF.lastCmd;
            PerformIt;
            END;
        {$IFC fTrace}EP;{$ENDC}
    END;
*)

    {$S sStartup}
    PROCEDURE {TWindow.}PickStdCursor;
    BEGIN
        {$IFC fTrace}BP(7);{$ENDC}
        SetStdCursor(arrowCursor);
        {$IFC fTrace}EP;{$ENDC}
    END;
    {$S SgABCres}


{$IFC LibraryVersion > 20}
{$S SgABCcld}
    PROCEDURE {TWindow.}PrefixToName(VAR error, offset: INTEGER; VAR prefix, name: TFilePath);
    BEGIN
        {$IFC fTrace}BP(7);{$ENDC}
        PrefixToName(error, offset, WindowPtr(SELF.wmgrID), Pathname(prefix), Pathname(name));
        {$IFC fTrace}EP;{$ENDC}
    END;
{$S SgABCres}
{$ENDC}


    {$S SgABCpri}
    PROCEDURE {TWindow.}Print{(panel: TPanel; nixPgRange: BOOLEAN; nixWholeDialog: BOOLEAN)};
    VAR prPrfAlias:     TPrPrfAlias;
        indeedPrint:    BOOLEAN;
        isNewStyle:     BOOLEAN;
        document:       TDocManager;
{$IFC libraryVersion <= 20}	    { P E P S I }
        error:	        INTEGER;
        prIns:	        TPrIns;
{$ELSEC}			    { S P R I N G }
        prIns:	        TPrRec;
        prMode:	        PrMenuSuppress;
{$ENDC}
    BEGIN
        {$IFC fTrace}BP(7);{$ENDC}
        IF currentDocument <> NIL THEN
            document := currentDocument
        ELSE
            document := boundDocument;

        IF document = clipboard THEN
            prPrfAlias.reserve := clipPrintPref
        ELSE
            prPrfAlias.reserve := document.dataSegment.preludePtr^.PrintPref;

        PushFocus;
{$IFC libraryVersion <= 20}	    { P E P S I }
        indeedPrint :=  FPrInsDlg(error, prPrfAlias.prPrf, prPrfAlias.prIns, isNewStyle);
{$ELSEC}			    { S P R I N G }
        IF nixWholeDialog THEN
            prMode := ePrDialogSuppress
        ELSE
        IF nixPgRange THEN
            prMode := ePgRangeSuppress
        ELSE
            prMode := ePrNormal;

        indeedPrint := FPrInsDlg(prPrfAlias.prPrf, isNewStyle, prMode);
{$ENDC}
        PopFocus;

{$IFC libraryVersion <= 20}	    { P E P S I }
        IF error > 0 THEN
            process.Stop(phUnknown)     {PrMgr passed on an OS error}
        ELSE
{$ENDC}
            BEGIN
            IF isNewStyle THEN  {style changed during print-instance dialog}
                SELF.AcceptNewPrinterInfo(document, prPrfAlias.reserve);

            IF indeedPrint THEN
                BEGIN
                amPrinting := TRUE;
                PushFocus;
                panel.PrintView(prPrfAlias.reserve);
                amPrinting := FALSE;
                PopFocus;

                SELF.Update(TRUE); {clear out white area from RECORDING box}
{$IFC libraryVersion <= 20}	    { P E P S I }
                PrBgdDlg(error, FALSE);	  {put up background dialog}
{$ENDC}	 {NB: For Spring, user-interface says we go back to the app, not to the background dialog}
                END;
            END;
        {$IFC fTrace}EP;{$ENDC}
    END;
    {$S SgABCres}


    {$S SgABCcld}
    PROCEDURE {TWindow.}PutUpDialogBox{(dialogBox: TDialogBox)};
    BEGIN
        {$IFC fTrace}BP(7);{$ENDC}
        SELF.CommitLast;
        SELF.dialogBox := dialogBox;
(*      IF dialogBox.selectWindow <> NIL THEN
            SELF.selectWindow := dialogBox.selectWindow;  *)  {+SW+}
        dialogBox.Appear;
        {$IFC fTrace}EP;{$ENDC}
    END;
    {$S SgABCres}


{$S sStartup}
    PROCEDURE {TWindow.}Refresh{(rActions: TActions; highTransit: THighTransit)};

        PROCEDURE RefreshPanel(obj: TObject);
            VAR panel:  TPanel;
        BEGIN
            panel := TPanel(obj);
            IF RectIsVisible(panel.outerRect) THEN
                panel.Refresh(rActions, highTransit);
        END;

    BEGIN
        {$IFC fTrace}BP(7);{$ENDC}
        IF SELF = clipboard.window THEN
            highTransit := hNone;
        {$IFC fDbgABC}
        IF (rBackground IN rActions) AND (highTransit > hOffToOn) THEN
            ABCBreak('Refresh: rBackground requested, but highTransit does not start from Off', 0);
        {$ENDC}
        IF rFrame IN rActions THEN
            SELF.Frame;
        SELF.panels.Each(RefreshPanel);
        {$IFC fTrace}EP;{$ENDC}
    END;
{$S SgABCres}


    {$S sStartup}
    PROCEDURE {TWindow.}Resize{(moving: BOOLEAN)};
            {Make the Tool Kit data structures agree with the window manager's idea of the window size;
                also, ensure that bottom right corner of window is on the screen}
        VAR oldOuterRect:       Rect;
            myGrafPort:	        GrafPtr;
            newScreenRect:      Rect;
            proposedSize:       Point;
            minExtent:	        Point;
            newOuterRect:       Rect;
            currentlyVisible:   BOOLEAN;
    BEGIN
        {$IFC fTrace}BP(7);{$ENDC}
        PushFocus;
        SELF.Focus;

        currentlyVisible := SELF.IsVisible;
        myGrafPort:= POINTER(SELF.wmgrID);

        IF currentlyVisible THEN
            BEGIN
            { Find out where the window is on the screen }
            newScreenRect := myGrafPort^.portRect;

            proposedSize := Point(FDiagRect(newScreenRect));

            IF NOT SELF.believeWmgr THEN
                WITH SELF DO
                    BEGIN
                    maxInnerSize := proposedSize;
                    believeWmgr := TRUE;
                    END;

            IF moving THEN { Constrain it to the maximum explicitly set by the user }
                BEGIN
                LocalToGlobal(newScreenRect.topLeft);
                { Propose the window botRight be at the screen botRight }
                proposedSize := Point(FPtMinPt(Point(FPtMinusPt(screenBits.bounds.botRight,
                                                                newScreenRect.topLeft)),
                                               SELF.maxInnerSize));
                END;
            END
        ELSE
            proposedSize := Point(FDiagRect(SELF.innerRect));

        { But be sure it is at least the minimum size }
        SELF.GetMinExtent(minExtent, TRUE);
        proposedSize := Point(FPtMaxPt(proposedSize, minExtent));

        IF NOT moving THEN
            SELF.maxInnerSize := proposedSize;

        oldOuterRect := SELF.outerRect;
        SetRect(newScreenRect, 0, 0, proposedSize.h, proposedSize.v);

        IF currentlyVisible THEN
            { finally set the wmgr window ("folder") size. }
            FolderSize(myGrafPort, proposedSize.h, proposedSize.v, FALSE);

        { Reset our idea of window's size }
        SELF.SetInnerRect(newScreenRect);

        ClipRect(SELF.innerRect);
        focusRgn := thePort^.visRgn;
        newOuterRect := SELF.outerRect;
        IF NOT EqualPt(oldOuterRect.botRight, newOuterRect.botRight) THEN
            SELF.panelTree.ResizeOutside(newOuterRect);

        PopFocus;
        {$IFC fTrace}EP;{$ENDC}
    END;
    {$S SgABCres}


    {$S SgABCcld}
    PROCEDURE {TWindow.}ResizeTo{(newSize: Point)};
    BEGIN
        {$IFC fTrace}BP(7);{$ENDC}
        IF NOT EqualPt(Point(FDiagRect(SELF.innerRect)), newSize) THEN
            BEGIN
            FolderSize(POINTER(SELF.wmgrID), newSize.h, newSize.v, FALSE);
            SELF.Resize(FALSE);
            END;
        {$IFC fTrace}EP;{$ENDC}
    END;
    {$S SgABCres}



    {$S sRes}
    PROCEDURE {TWindow.}RestoreSelection;
        PROCEDURE RestoreSel(obj: TObject);
        BEGIN
            TPanel(obj).undoSelection.Restore;  {$}
        END;

    BEGIN
        {$IFC fTrace}BP(7);{$ENDC}
        SELF.selectPanel := SELF.undoSelPanel;
        SELF.clickPanel := SELF.undoClickPanel;
        SELF.selectWindow := SELF.undoSelWindow; {+SW+}
        SELF.panels.Each(RestoreSel);
        IF SELF.dialogBox <> NIL THEN
            SELF.dialogBox.RestoreSelection;
        {$IFC fTrace}EP;{$ENDC}
    END;



    {$S sCommand}
    PROCEDURE {TWindow.}RevealSelection(asMuchAsPossible, doHilite: BOOLEAN);
        PROCEDURE RevlSel(obj: TObject);
        BEGIN
            TPanel(obj).selection.Reveal(asMuchAsPossible);
        END;

    BEGIN
        {$IFC fTrace}BP(7);{$ENDC}
        SELF.Update(doHilite);
        SELF.panels.Each(RevlSel);
        SELF.Update(doHilite);
        {$IFC fTrace}EP;{$ENDC}
    END;


    {$S sCommand}
    PROCEDURE {TWindow.}SaveCommand{(command: TCommand)};

        PROCEDURE SaveUndoSelection(obj: TObject);
            VAR panel: TPanel;
                sel:   TSelection;
        BEGIN
            panel := TPanel(obj);
            sel := panel.undoSelection.FreedAndReplacedBy(TSelection(panel.selection.Clone(SELF.Heap)));
        END;

    BEGIN  {Called by PerformCommand between NewCommand & PerformLast to establish an undo-point}
        {$IFC fTrace}BP(7);{$ENDC}
        IF SELF <> currentWindow THEN
            currentWindow.SaveCommand(command)  {probably this is a dialog box}
        ELSE
        IF SELF.lastCmd <> NIL THEN
            SELF.lastCmd.Become(command)
        ELSE
            SELF.lastCmd := command;

        SELF.panels.Each(SaveUndoSelection);
        {$IFC fTrace}EP;{$ENDC}
    END;


    {$S sCommand}
    PROCEDURE {TWindow.}SaveSelection;
        PROCEDURE SaveSel(obj: TObject);
        BEGIN
            TPanel(obj).selection.Save;
        END;

    BEGIN
        {$IFC fTrace}BP(7);{$ENDC}
        SELF.panels.Each(SaveSel);
        SELF.undoSelPanel := SELF.selectPanel;
        SELF.undoClickPanel := SELF.clickPanel;
        SELF.undoSelWindow := SELF.selectWindow; {+SW+}
        IF SELF.dialogBox <> NIL THEN
            SELF.dialogBox.SaveSelection;
        {$IFC fTrace}EP;{$ENDC}
    END;
{$}


    {$S sCommand}
    PROCEDURE {TWindow.}SetupMenus;
        VAR anS255:     S255;
            undoTempl:  TCmdNumber;
            mapHandle:  TMapHandle;
            selection:  TSelection;
            i:	        INTEGER;
            wmgrCmd:    TWmgrCmd;
            checkIt:    BOOLEAN;
            mainWindow: TWindow;
    BEGIN  {NOTE: wmgrMenus[menuIndex] can not be assigned to a local variable because it is passed as a VAR}
        {$IFC fTrace}BP(5);{$ENDC}
        mainWindow := currentWindow;

        {First, change the text of the Set Aside and Undo items.}
        mainWindow.GetTitle(anS255); {don't use SELF because we might be a dialog box}
        anS255 := CONCAT('"', anS255, '"');
        menuBar.BuildCmdName(uSetAside, utSetAside, @anS255);
        menuBar.BuildCmdName(uSetClipAside, utSetAside, @anS255);

        IF mainWindow.lastCmd = NIL THEN {the mainWindow always has the last command}
            menuBar.BuildCmdName(uUndoLast, utUndoLast, NIL)
        ELSE
            BEGIN
            IF mainWindow.lastCmd.doing THEN
                undoTempl := utUndoLast
            ELSE
                undoTempl := utRedoLast;

            IF menuBar.GetCmdName(mainWindow.lastCmd.cmdNumber, @anS255) THEN
                BEGIN
                anS255 := CONCAT('"', anS255, '"');
                menuBar.BuildCmdName(uUndoLast, undoTempl, @anS255);
                END
            ELSE
                menuBar.BuildCmdName(uUndoLast, undoTempl, NIL);
            END;

        {Then enable and check the appropriate items}
        mapHandle := TMapHandle(menuBar.mapping);
        selection := SELF.selectPanel.selection;

        FOR i := 1 TO menuBar.numCommands DO
            BEGIN
            wmgrCmd := mapHandle^^.table[i];
            WITH wmgrCmd DO
                IF menuBar.isLoaded[menuIndex] THEN
                    BEGIN
                    checkIt := FALSE;

                    (**********
                    IF selection.CanDoCommand(cmdNumber, checkIt) THEN
                        EnableItem(wmgrMenus[menuIndex], itemIndex)
                    ELSE
                        DisableItem(wmgrMenus[menuIndex], itemIndex);
                    **********)

                   {The following line is an optimization for the preceding}
                    wmgrMenus[menuIndex].enableFlags[itemIndex] :=
                        selection.CanDoCommand(cmdNumber, checkit);
                    CheckItem(wmgrMenus[menuIndex], itemIndex, checkIt);
                    END;
            END;
        {$IFC fTrace}EP;{$ENDC}
    END;


    {$S SgABCini}
    PROCEDURE {TWindow.}SetWmgrId{(itsWmgrId: TWindowID)};
    VAR panelScanner:   TListScanner;
        panel:	        TPanel;
        paneScanner:    TListScanner;
        pane:	        TPane;
    BEGIN
        {$IFC fTrace}BP(7);{$ENDC}
        SELF.wmgrId := itsWmgrId;
        panelScanner := SELF.panels.Scanner;
        WHILE panelScanner.Scan(panel) DO
            BEGIN
            paneScanner := panel.panes.Scanner;
            WHILE paneScanner.Scan(pane) DO
                pane.port := POINTER(itsWmgrId);
            END;
        {$IFC fTrace}EP;{$ENDC}
    END;
    {$S SgABCres}


    {$S SgABCcld}
    PROCEDURE {TWindow.}StashPicture{(highTransit: THighTransit)};
    BEGIN
        {$IFC fTrace}BP(7);{$ENDC}
        RectRgn(altVisRgn, SELF.outerRect);
        useAltVisRgn := TRUE;   {Make TPad.Focus use altVisRgn instead of visRgn}

        PushFocus;
        SELF.Focus;

        WMOpenPicture(POINTER(SELF.wmgrID));
        SELF.Refresh([rErase, rFrame, rBackground, rDraw], highTransit); {recorded & not displayed}
        WMClosePicture;

        useAltVisRgn := FALSE;

        PopFocus;
        {$IFC fTrace}EP;{$ENDC}
    END;
    {$S SgABCres}


    {$S SgABCcld}
    PROCEDURE {TWindow.}TakeDownDialogBox;  {+sw+}
        VAR dialogBox: TDialogBox;
    BEGIN
        {$IFC fTrace}BP(7);{$ENDC}
        {Don't CommitLast here, because the Dialog Box may have created a command that can be undone later}
        dialogBox := SELF.dialogBox;
        IF dialogBox <> NIL THEN
            BEGIN
            IF SELF.lastCmd <> NIL THEN
                IF SELF.lastCmd.image <> NIL THEN
                    IF SELF.lastCmd.image.view.panel.window = dialogBox THEN
                        SELF.CommitLast;  {+sw+}

            dialogBox.Disappear;
            IF dialogBox.freeOnDismissal THEN
                SELF.objectToFree := dialogBox; {+SW+}	 {will be freed at end of event loop}
            SELF.dialogBox := NIL;
            SELF.selectWindow := SELF;
            END
        ELSE
            ABCBreak('TakeDownDialogBox, but none up', 0);
        {$IFC fTrace}EP;{$ENDC}
    END;
    {$S SgABCres}


    {$IFC fDbgABC}
    {$S SgABCdbg}
    PROCEDURE {TWindow.}ToggleFlag{(VAR flag: BOOLEAN)};
    BEGIN
        {$IFC fTrace}BP(1);{$ENDC}
        flag := NOT flag;
        {$IFC fTrace}EP;{$ENDC}
    END;
    {$S SgABCres}
    {$ENDC}


    {$S SgABCcld}
    PROCEDURE {TWindow.}UndoLast;
    VAR lastCmd:    TCommand;
        str:	    S255;
        cmdPhase:   TCmdPhase;
    BEGIN
        {$IFC fTrace}BP(7);{$ENDC}
        IF SELF <> currentWindow THEN
            currentWindow.UndoLast
        ELSE
            BEGIN
            lastCmd := SELF.lastCmd;
            IF lastCmd = NIL THEN
                process.Stop(phNoCommand)
            ELSE
            IF NOT lastCmd.undoable THEN
                BEGIN
                IF NOT menuBar.GetCmdName(lastCmd.cmdNumber, @str) THEN
                    BEGIN
                    {$IFC fDbgABC} ABCbreak('TCommand.cmdNumber not in menu', lastCmd.cmdNumber); {$ENDC}
                    str := 'Last Command';
                    END;
                process.ArgAlert(1, str);
                process.Stop(phCantUndo);
                END
            ELSE
            IF lastCmd.doing THEN
                SELF.PerformLast(undoPhase)
            ELSE
                SELF.PerformLast(redoPhase);
            END;
        {$IFC fTrace}EP;{$ENDC}
    END;
    {$S SgABCres}


    {$S sStartup}
    PROCEDURE {TWindow.}Update{(doHilite: BOOLEAN)};
        VAR pWindow:	    WindowPtr;
            updateRgn:	    RgnHandle;
            highTransit:    THighTransit;
    BEGIN
        {$IFC fTrace}BP(7);{$ENDC}
        PushFocus;
        SELF.Focus;
        pWindow := POINTER(SELF.wmgrID);
        BeginUpdate(pWindow);
        updateRgn := pWindow^.visRgn;
        IF NOT EmptyRgn(updateRgn) THEN
            BEGIN
            IF doHilite THEN
                highTransit := highLevel[SELF.isActive]
            ELSE
                highTransit := hNone;
            FillRgn(updateRgn, white);
            SELF.Refresh([rFrame, rBackground, rDraw], highTransit);
            END;
        EndUpdate(pWindow);
        PopFocus;
        {$IFC fTrace}EP;{$ENDC}
    END;
{$S SgABCres}


    {$S sStartup}
    FUNCTION  {TWindow.}WantMenu{(menuID: INTEGER; inClipboard: BOOLEAN): BOOLEAN};
    BEGIN
        {$IFC fTrace}BP(3);{$ENDC}
        IF inClipboard THEN
            WantMenu := menuID = mnuClipFilePrint
        ELSE
            WantMenu := (menuID < mBuzzword);
        {$IFC fTrace}EP;{$ENDC}
    END;
    {$S SgABCres}


{$S SgABCini}
END;
{$S SgABCres}


METHODS OF TDialogBox;


    {$S SgABCcld}
    FUNCTION  {TDialogBox.}CREATE{(object: TObject; heap: THeap; itsResizability: BOOLEAN; itsHeight: INTEGER;
                                   itsKeyResponse, itsMenuResponse,
                                   itsDownInMainWindowResponse: TDiResponse): TDialogBox};
        VAR diBxRect: Rect;
    BEGIN
        {$IFC fTrace}BP(7);{$ENDC}
        IF object = NIL THEN
            object := NewObject(heap, THISCLASS);
        SELF := TDialogBox(TWindow.CREATE(object, heap, ORD(dialogFolder), itsResizability));

        WITH SELF DO
            BEGIN
            keyResponse := itsKeyResponse;
            menuResponse := itsMenuResponse;
            downInMainWindowResponse := itsDownInMainWindowResponse;
            freeOnDismissal := FALSE; {+SW+}
            END;
        SELF.GetPrinterMetrics; {mostly just so that these won't be total garbage in debug output}
        SetRect(diBxRect, 0, 0, screenBits.bounds.right, itsHeight);
        SELF.SetInnerRect(diBxRect);
        {$IFC fTrace}EP;{$ENDC}
    END;
    {$S SgABCres}


    {$IFC fDebugMethods}
    {$S SgABCdbg}
    PROCEDURE {TDialogBox.}Fields{(PROCEDURE Field(nameAndType: S255))};
    BEGIN
        TWindow.Fields(Field);
        Field('keyResponse: Byte');
        Field('menuResponse: Byte');
        Field('downInMainWindowResponse: Byte');
        Field('freeOnDismissal: BOOLEAN');  {+SW+}
        Field('');
    END;
    {$S SgABCres}
    {$ENDC}


    {$S SgABCcld}
    PROCEDURE {TDialogBox.}Appear;
    BEGIN
        {$IFC fTrace}BP(7);{$ENDC}
        DialogHeight(LengthRect(SELF.innerRect, v), TRUE);
        SELF.outerRect.bottom := SELF.outerRect.top; {force Resize to recalculate everything}
        SELF.Resize(FALSE);
        {$IFC fTrace}EP;{$ENDC}
    END;


    {$S SgABCcld}
    PROCEDURE {TDialogBox.}BeDismissed;
    BEGIN
        {$IFC fTrace}BP(7);{$ENDC}
        currentWindow.TakeDownDialogBox;
        {$IFC fTrace}EP;{$ENDC}
    END;


    {$S SgABCcld}
    PROCEDURE {TDialogBox.}Disappear;
    BEGIN
        {$IFC fTrace}BP(7);{$ENDC}
        DialogHeight(0, FALSE);
        SELF.believeWmgr := FALSE; {the window's innerRect is known to NOT match the size of the dialog box}
        {$IFC fTrace}EP;{$ENDC}
    END;


    {$S SgABCcld}
    PROCEDURE {TDialogBox.}GetMinExtent{(VAR minExtent: Point; windowIsResizingIt: BOOLEAN)};
    BEGIN
        {$IFC fTrace}BP(9);{$ENDC}
        SUPERSELF.GetMinExtent(minExtent, windowIsResizingIt);
        minExtent.h := screenBits.bounds.right;
        {$IFC fTrace}EP;{$ENDC}
    END;
    {$S SgABCres}


    {$S SgABCcld}
    FUNCTION  {TDialogBox.}IsVisible{: BOOLEAN};
        VAR info:   WindowInfo;
    BEGIN
        {$IFC fTrace}BP(3);{$ENDC}
        IF SUPERSELF.IsVisible THEN
            IsVisible := currentWindow.dialogBox = SELF
        ELSE
            IsVisible := FALSE;
        {$IFC fTrace}EP;{$ENDC}
    END;
    {$S SgABCres}


{$S SgABCini}
END;
{$S SgABCres}


{SUBROUTINES OF TMenuBar}


    {$S sRes}
PROCEDURE InAllMenusDo{(iffLoaded: BOOLEAN; theCommand: TCmdNumber;
                        PROCEDURE doProc(VAR menu: MenuInfo; itemIndex: INTEGER))};
    VAR i:	    INTEGER;
        lowIDX:	    INTEGER;
        highIDX:    INTEGER;
        mapHandle:  TMapHandle;
        fFound:	    BOOLEAN;
BEGIN
    fFound := FALSE;
    mapHandle := TMapHandle(menuBar.mapping);
    lowIDX := 1;
    highIDX := menuBar.numCommands;

    WHILE NOT fFound AND (lowIdx <= highIdx) DO
        BEGIN
        i := (lowIDX+highIDX) DIV 2;
  {$R-} WITH mapHandle^^.table[i] DO {$IFC fRngABC}{$R+}{$ENDC} { OK to do this because once
                              we call doProc, we don't refer to this record any more }
            IF theCommand = cmdNumber THEN
                BEGIN
                fFound := TRUE;
                IF menuBar.isLoaded[menuIndex] = iffLoaded THEN
                    doProc(wmgrMenus[menuIndex], itemIndex);
                END
            ELSE
            IF theCommand > cmdNumber THEN
                lowIDX := i+1
            ELSE
                highIDX := i-1;
        END;
END;


    {$S sCommand}
FUNCTION  CmdFromWmgr(menuId, itemIndex: INTEGER): TCmdNumber;
    VAR wmgrCmd:    TWmgrCmd;
        cmdNumber:  TCmdNumber;
        i:	    INTEGER;
        mapHandle:  TMapHandle;
BEGIN {does not need to be very fast}
        {$IFC fMaxTrace}BP(1);{$ENDC}
        {$IFC fMaxTrace}EP;{$ENDC}
    IF itemIndex < 0 THEN
        CmdFromWmgr := -itemIndex {this is how we will implement graphical menus}
    ELSE
        BEGIN
        mapHandle := TMapHandle(menuBar.mapping);
        FOR i := 1 TO menuBar.numCommands DO
            BEGIN
            {$R-}
            wmgrCmd := mapHandle^^.table[i];
            {$IFC fRngABC}{$R+}{$ENDC}
            IF wmgrCmd.itemIndex = itemIndex THEN
                IF menuBar.isLoaded[wmgrCmd.menuIndex] THEN
                    IF wmgrMenus[wmgrCmd.menuIndex].menuId = menuId THEN
                        BEGIN
                        CmdFromWmgr := wmgrCmd.cmdNumber;
                        EXIT(CmdFromWmgr);
                        END;
             END;
        CmdFromWmgr := 0;
        END;
END;


    {$S sRes}
FUNCTION  FindMenu(menuID: INTEGER): INTEGER;
    { given a menuID (the number in the phrase file) return the menuIndex into
        our array of menuInfo records }
VAR menuIndex:  INTEGER;
BEGIN
        {$IFC fMaxTrace}BP(1);{$ENDC}
        {$IFC fMaxTrace}EP;{$ENDC}
    FOR menuIndex := 1 TO menuBar.numMenus DO
        IF wmgrMenus[menuIndex].menuID = menuID THEN
            BEGIN
            FindMenu := menuIndex;
            EXIT(FindMenu);
            END;
    FindMenu := 0;
END;


METHODS OF TMenuBar;


    {$S SgABCini}
    FUNCTION  {TMenuBar.}CREATE{(object: TObject; heap: THeap; itsScanner: TFileScanner): TMenuBar};
        VAR menu:	    MenuInfo;
            numMenus:	    INTEGER;
            i:		    INTEGER;
            numBytes:	    INTEGER;
            mapping:	    TArray;
            numCommands:    INTEGER;
    BEGIN
        {$IFC fTrace}BP(7);{$ENDC}
        IF object = NIL THEN
            object := NewObject(heap, THISCLASS);
        SELF := TMenuBar(object);

        menu.drawProc := @drawTxtMenu;
        menu.chooseProc := @chooseTxtItem;
        numMenus := itsScanner.ReadNumber(2);
        SELF.numMenus := numMenus;
        FOR i := 1 TO numMenus DO
            BEGIN
            menu.menuId := itsScanner.ReadNumber(2);
            itsScanner.XferSequential(xRead, @menu.enableFlags, 4);
            numBytes := itsScanner.ReadNumber(2);
            menu.menuData := POINTER(ORD(HAllocate(POINTER(ORD(heap)), numBytes)));
            itsScanner.XferSequential(xRead, @menu.menuData^^, numBytes);
            CalcMenuSize(menu);
            wmgrMenus[i] := menu;
            SELF.isLoaded[i] := FALSE;
            END;
        mapping := POINTER(ORD(itsScanner.ReadArray(heap, SIZEOF(TWmgrCmd))));
        SELF.mapping := mapping;
        numCommands := mapping.Size;
        SELF.numCommands := numCommands;
        InitErrorAbort(itsScanner.error);
        {$IFC fTrace}EP;{$ENDC}
    END;
    {$S SgABCres}


    {$IFC fDebugMethods}
    {$S SgABCdbg}
    PROCEDURE {TMenuBar.}Fields{(PROCEDURE Field(nameAndType: S255))};
    BEGIN
        Field('isLoaded: ARRAY [1..31] OF BOOLEAN');   (* MaxMenus = 31 *)
        Field('mapping: TArray');
        Field('numMenus: INTEGER');
        Field('numCommands: INTEGER');
    END;
    {$S SgABCres}
    {$ENDC}


    {$S sRes}
    PROCEDURE {TMenuBar.}BuildCmdName{(destCmd, templateCmd: TCmdNumber; param: TPString)};
    VAR templ:  S255;
        xStart: INTEGER;
        xEnd:   INTEGER;
    BEGIN
        {$IFC fTrace}BP(3);{$ENDC}
        IF SELF.GetCmdName(templateCmd, @templ) THEN
            BEGIN
            xStart := POS('^', templ);
            IF xStart > 0 THEN
                BEGIN
                DELETE(templ, xStart, 1);

                xEnd := POS('^', templ);
                IF xEnd > 0 THEN
                    DELETE(templ, xEnd,1)
                ELSE
                    xEnd := LENGTH(templ) + 1;

                IF param <> NIL THEN
                    BEGIN
                    DELETE(templ, xStart, xEnd-xStart);
                    INSERT(param^, templ, xStart);
                    END;
                END;

            SELF.PutCmdName(destCmd, @templ);
            END;
        {$IFC fTrace}EP;{$ENDC}
    END;


    {$S sRes}
    PROCEDURE {TMenuBar.}Check{(cmdNumber: TCmdNumber; checked: BOOLEAN)};
      Label 1;
        PROCEDURE DoCheck(VAR menu: MenuInfo; itemIndex: INTEGER);
        BEGIN
            CheckItem(menu, itemIndex, checked);
            Goto 1;
        END;
    BEGIN
        {$IFC fTrace}BP(2);{$ENDC}
        InAllMenusDo(TRUE, cmdNumber, DoCheck);
    1:  {$IFC fTrace}EP;{$ENDC}
    END;


    {$S sCommand}
    FUNCTION  {TMenuBar.}CmdKey{(ch: CHAR): TCmdNumber};
        VAR menuId, itemIndex: INTEGER;
    BEGIN
        {$IFC fTrace}BP(7);{$ENDC}
        MenuKey(ch, menuId, itemIndex);
        if menuId <> 0 THEN
            HiLiteMenu(menuId);
        CmdKey := CmdFromWmgr(menuId, itemIndex);
        {$IFC fTrace}EP;{$ENDC}
    END;


    {$S sRes}
    PROCEDURE {TMenuBar.}Delete{(menuID: INTEGER)};
        VAR menuIndex:  INTEGER;
    BEGIN
        {$IFC fTrace}BP(7);{$ENDC}
        DeleteMenu(menuId);
        menuIndex := FindMenu(menuID);
        IF menuIndex > 0 THEN
            SELF.isLoaded[menuIndex] := FALSE;
        {$IFC fTrace}EP;{$ENDC}
    END;


    {$S sCommand}
    FUNCTION  {TMenuBar.}DownAt{(mousePt: Point): TCmdNumber};
        VAR menuId, itemIndex: INTEGER;
    BEGIN
        {$IFC fTrace}BP(7);{$ENDC}
        process.ChangeCursor(arrowCursor);
        MenuSelect(mousePt, menuId, itemIndex);
        if menuId <> 0 THEN
            HiLiteMenu(menuId);
        DownAt := CmdFromWmgr(menuId, itemIndex);
        {$IFC fTrace}EP;{$ENDC}
    END;


    {$S sStartup}
    PROCEDURE {TMenuBar.}Draw;
    BEGIN
        {$IFC fTrace}BP(7);{$ENDC}
        DrawMenuBar;
        {$IFC fTrace}EP;{$ENDC}
    END;


    {$S sRes}
    PROCEDURE {TMenuBar.}Enable{(cmdNumber: TCmdNumber; canBeChosen: BOOLEAN)};
    BEGIN
        {$IFC fTrace}BP(2);{$ENDC}
        IF canBeChosen THEN
            InAllMenusDo(TRUE, cmdNumber, EnableItem)
        ELSE
            InAllMenusDo(TRUE, cmdNumber, DisableItem);
        {$IFC fTrace}EP;{$ENDC}
    END;


    {$S sRes}
    PROCEDURE {TMenuBar.}EndCmd;
    BEGIN
        {$IFC fTrace}BP(6);{$ENDC}
        HiLiteMenu(0);
        {$IFC fTrace}EP;{$ENDC}
    END;


    {$S sRes}
    FUNCTION  {TMenuBar.}GetCmdName{(cmdNumber: TCmdNumber; pName: TPString): BOOLEAN};
      Label 1;
        PROCEDURE DoGet(VAR menu: MenuInfo; itemIndex: INTEGER);
            VAR kludge: Str255;
        BEGIN
            IF pName <> NIL THEN
                BEGIN
                GetItem(menu, itemIndex, @kludge);
                XferLeft(@kludge, POINTER(ORD(pName)), LENGTH(kludge)+1);
                END;
            Goto 1;
        END;
    BEGIN
        {$IFC fTrace}BP(6);{$ENDC}
        GetCmdName := TRUE;
        InAllMenusDo(TRUE, cmdNumber, DoGet);
        InAllMenusDo(FALSE, cmdNumber, DoGet);
        GetCmdName := FALSE;
        IF pName <> NIL THEN
            pName^ := '';
    1:  {$IFC fTrace}EP;{$ENDC}
    END;


    {$S sRes}
    PROCEDURE {TMenuBar.}HighlightMenu(withCmd: TCmdNumber);
        LABEL   1;

        PROCEDURE DoHighlight(VAR menu: MenuInfo; itemIndex: INTEGER);
        BEGIN
            HiLiteMenu(menu.menuID);
            Goto 1;
        END;
    BEGIN
        {$IFC fTrace}BP(6);{$ENDC}
        InAllMenusDo(TRUE, withCmd, DoHighlight);
1:      {$IFC fTrace}EP;{$ENDC}
    END;


    {$S sStartup}
    PROCEDURE {TMenuBar.}Insert{(menuID, beforeId: INTEGER)};
        VAR menuIndex:  INTEGER;
    BEGIN
        {$IFC fTrace}BP(7);{$ENDC}
        menuIndex := FindMenu(menuID);
        IF menuIndex > 0 THEN
            BEGIN
            InsertMenu(wmgrMenus[menuIndex], beforeId);
            SELF.isLoaded[menuIndex] := TRUE;
            END;
        {$IFC fTrace}EP;{$ENDC}
    END;


    {$S SgABCcld}
    FUNCTION  {TMenuBar.}MenuWithID(menuID: INTEGER): Ptr;
        VAR menuIndex:  INTEGER;
    BEGIN
        {$IFC fTrace}BP(7);{$ENDC}
        menuIndex := FindMenu(menuID);
        IF menuIndex > 0 THEN
            MenuWithId := @wmgrMenus[menuIndex]
        ELSE
            MenuWithID := NIL;
        {$IFC fTrace}EP;{$ENDC}
    END;


    {$S sRes}
    PROCEDURE {TMenuBar.}PutCmdName{(cmdNumber: TCmdNumber; pName: TPString)};
        Label 1;
        VAR kludge: Str255;
        PROCEDURE DoPut(VAR menu: MenuInfo; itemIndex: INTEGER);
        BEGIN
            SetItem(menu, itemIndex, @kludge);
            Goto 1;
        END;
    BEGIN
        {$IFC fTrace}BP(6);{$ENDC}
        XferLeft(POINTER(ORD(pName)), @kludge, LENGTH(pName^)+1);
        InAllMenusDo(TRUE, cmdNumber, DoPut);
        InAllMenusDo(FALSE, cmdNumber, DoPut);
    1:  {$IFC fTrace}EP;{$ENDC}
    END;


(**********
{$S SgABCini}
    PROCEDURE {TMenuBar.}SetupGrMenu(menuID: INTEGER; width, height: INTEGER;
                                        newChooseProc, newDrawProc: Ptr);
        {if either proc is NIL, don't change the current value;
         if either width or height is <= 0, don't change the current value;
         when the menu is first read in, it is setup to behave like a standard text menu}
        VAR menuIndex:  INTEGER
    BEGIN
        {$IFC fTrace}BP(7);{$ENDC}
        menuIndex := FindMenu(menuID);
        IF menuIndex > 0 THEN
            WITH wmgrMenus[menuIndex] DO
                BEGIN
                IF width > 0 THEN
                    menuWidth := width;
                IF height > 0 THEN
                    menuHeight := height;
                IF newChooseProc <> NIL THEN
                    chooseProc := newChooseProc;
                IF newDrawProc <> NIL THEN
                    drawProc := newDrawProc;
                END;
        {$IFC fTrace}EP;{$ENDC}
    END;
{$S SgABCres}
**********)


    {$S sRes}
    PROCEDURE {TMenuBar.}Unload;
        VAR i:  INTEGER;
    BEGIN
        {$IFC fTrace}BP(7);{$ENDC}
        ClearMenuBar;
        FOR i := 1 TO SELF.numMenus DO
            SELF.isLoaded[i] := FALSE;
        {$IFC fTrace}EP;{$ENDC}
    END;


{$S SgABCini}
END;
{$S SgABCres}


{$IFC LibraryVersion <= 20 AND FALSE} {do it this way in case we need it back for the Pepsi version}
METHODS OF TFont;


    {$S SgABCini}
    FUNCTION  {TFont.}CREATE{(object: TObject; heap: THeap; itsFamily: INTEGER): TFont};
    BEGIN
        {$IFC fTrace}BP(7);{$ENDC}
        IF object = NIL THEN
            object := NewObject(heap, THISCLASS);
        SELF := TFont(object);

        SELF.family := itsFamily;
        {$IFC fTrace}EP;{$ENDC}
    END;
    {$S SgABCres}


    {$IFC fDebugMethods}
    {$S SgABCdbg}
    PROCEDURE {TFont.}Fields{(PROCEDURE Field(nameAndType: S255))};
    BEGIN
        Field('family: INTEGER');
    END;
    {$S SgABCres}
    {$ENDC}


{$S SgABCini}
END;
{$S SgABCres}
{$ENDC}




